Rencontres R 2024
https://github.com/tvroylandt/rr_2024
Cas réels, dans le cadre de production d’indicateurs pour un service statistique ministériel
Une grande créativité dans les mises en forme des données !
Captures d’écrans qui se superpose de fichiers Excel en bordel avec smileys de réactions
Population active et taux d’activité au sens du recensement selon le sexe et l’âge en 2020 : comparaisons départementales
Intitulés des colonnes fusionnées
Zone des données décalée
readxlEn spécifiant les colonnes à la main
readxltidyxlxlsx_cells donne un tibble de la localisation et du contenu des cellules
tidyxl + unpivotr
tidyxl + unpivotr
up-left car une cellule fusionnée ne remplit que le haut à gauche
tidyxl + unpivotr
tidyxl + unpivotr
tidyxl + unpivotr
tidyxl + unpivotrRépartition des naissances par âge de la mère
Début des données décalées
Intitulés des colonnes fusionnées
Un onglet par année (mais tous pareil) + un onglet de documentation
Des données à la fin que l’on ne souhaite pas importer
readxlOn prend les colonnes telles quelles
readxlIdem sur les onglets dans un map
excel_sheets(path_c24) |>
set_names() |>
_[-12] |>
map(read_xlsx,
path = path_c24,
skip = 5,
.name_repair = "unique_quiet") |>
list_rbind(names_to = "annee") |>
rename(code_dep = ...1,
lib_dep = ...2) |>
pivot_longer(-c(annee, code_dep, lib_dep),
names_to = "age_mere",
values_to = "perc_naiss") |>
mutate(annee = as.numeric(annee)) |>
filter(!is.na(code_dep) &
!is.na(perc_naiss) &
!code_dep %in% c("F", "M"))readxltidyxltidyxl + dplyr/tidyrdf_cells_c24 |>
filter(sheet != "Documentation") |>
filter(row >= 4 & !is_blank & col != 2) |>
select(sheet, row, col, character, numeric) |>
mutate(header_row = case_when(row == 6 ~ character),
code_dep = case_when(col == 1 ~ coalesce(as.character(numeric), character))) |>
group_by(col) |>
fill(header_row, .direction = "down") |>
group_by(row) |>
fill(code_dep, .direction = "down") |>
ungroup() |>
filter(!is.na(numeric) &
!is.na(code_dep) &
!is.na(header_row) & !code_dep %in% c("F", "M")) |>
mutate(sheet = as.numeric(sheet),
header_row = str_trim(header_row)) |>
select(annee = sheet,
code_dep,
age_mere = header_row,
perc_naiss = numeric)tidyxl + unpivotrpenser à grouper par onglet
df_cells_c24 |>
filter(row >= 5) |>
group_by(sheet) |>
behead("up-left", "typ_var") |>
behead("up", "mod_var") |>
behead("left", "code_dep") |>
behead("left", "lib_dep") |>
ungroup() |>
mutate(mod_var = str_trim(mod_var)) |>
select(sheet, typ_var, mod_var, code_dep, lib_dep, numeric) |>
filter(!is.na(code_dep) &
!code_dep %in% c("F", "M") &
!is.na(numeric)) tidyxl + unpivotrdplyr et tidyr comme fill ou coalesce en complémentstr_detectexemple pour récupérer les dates de MAJ de chaque onglet
Cela fonctionne dans la plupart des cas assez bien, même avec des cellules fusionnées et d’autres non
petite subtilité car tous les onglets ne commencent pas au même endroit et ne terminent pas au même endroit
df_cells_faj <- xlsx_cells("data/FAJ Données annuelles 2007-2022.xlsx") |>
# on filtre sur les onglets qui nous intéressent - on retire FAJ2015 qui a une structuration différente et qu'il faudrait traiter à part
filter(str_sub(sheet, 1, 6) == "FAJ 20" & sheet != "FAJ 2015")
# ligne de début
df_cells_faj_min <- df_cells_faj |>
filter(character == "Départements") |>
select(sheet, row_min = row)
# ligne de fin - on aurait aussi pu détecter La Réunion
df_cells_faj_max <- df_cells_faj |>
filter(is_blank & col == 1) |>
inner_join(df_cells_faj_min, by = join_by(sheet)) |>
# on ajoute quelques lignes
filter(row > row_min + 3) |>
group_by(sheet) |>
filter(row == min(row)) |>
ungroup() |>
select(sheet, row_max = row) |>
# comme on a detecté la ligne blanche suivant la fin, on décale
mutate(row_max = row_max - 1)
# on jointe pour cibler les tableaux
df_cells_faj |>
inner_join(df_cells_faj_min, by = join_by(sheet)) |>
inner_join(df_cells_faj_max, by = join_by(sheet)) |>
filter(between(row, row_min, row_max)) |>
group_by(sheet) |>
behead("up-left", "typ_var") |>
behead("up", "mod_var") |>
behead("left", "code_dep") |>
behead("left", "lib_dep") |>
ungroup() |>
select(sheet, typ_var, mod_var, code_dep, lib_dep, character, numeric)Tab 2022 avec deux tabs dans le même –> séparation des tabs plutôt que de ne faire que le premier
on va partitionner les cellules en tableaux, comme un nest, puis on va pouvoir soit travailler indépendemment, soit avec un map si la structure est similaire travailler le sujet
pour cela, il va falloir délimiter, ici on va le faire par les en-têtes, mais cela peut aussi se faire avec une détection des blancs (mais plus complexe avec les cellules fusionnées)
df_cells_faj_filtered <- df_cells_faj |>
filter(sheet == "FAJ 2022" & row >= 9)
df_title_cells_faj <- df_cells_faj_filtered |>
filter(character %in% c("Départements", "Métropoles et départements hors métropoles"))
# on partitionne
partitions_faj <- partition(df_cells_faj_filtered,
df_title_cells_faj)
# on reprendre le code du dessus
# et on assemble
map(
partitions_faj$cells,
\(data) data |>
behead("up-left", "typ_var") |>
behead("up", "mod_var") |>
behead("left", "code_dep") |>
behead("left", "lib_dep") |>
select(typ_var, mod_var, code_dep, lib_dep, character, numeric)
) |>
set_names("dep", "metro") |>
list_rbind(names_to = "type_geo")démo pour le format sous une autre forme que le texte (gras, couleur)
On va s’attacher à un seul tableau
path_panorama <- "data/PanoFrance2022.xlsx"
# chargement des cellules + délimitation
df_cells_panorama <- xlsx_cells(path_panorama) |>
filter(between(row, 330, 355))
# et du format - liste
format_panorama <- xlsx_formats(path_panorama)
df_panorama_cleaned <- df_cells_panorama |>
# il faudra gérer la fusion des codes géographiques à part
behead("up", "code_geo") |>
# type d'établissement en gras - penser à indexer sur le type d'établissement
behead_if(format_panorama$local$font$bold[local_format_id],
direction = "left-up",
name = "type_etab") |>
behead_if(
format_panorama$local$alignment$indent[local_format_id] == 2,
direction = "left-up",
name = "type_var"
) |>
behead_if(
format_panorama$local$alignment$indent[local_format_id] == 4,
direction = "left",
name = "type_places"
) |>
select(code_geo, type_etab, type_var, type_places, numeric, character) |>
filter(!is.na(numeric))
df_panorama_cleanedProduction statistique
Rapports statistiques
Politiques sociales et de l’emploi
Handicap
Récupération des données
Calcul des indicateurs
Mise en forme des fichiers
Validation
Documentation
Mise en ligne